using System;
using System.Data;
using Resources;

using System.Web;
using System.Collections;
using System.Collections.Specialized;
using System.Web.Services;
using System.Web.Services.Protocols;
using LtMbs.CrmSdkHelperClass;

using CrmServiceWebReference;
using KalDev;
namespace LtMbs
{
    /// <summary>
    /// ///
    /// ///    Notes exceptions, exclusions, or any other funny's you need 
    /// ///    to know about CombinedSearch
    /// ///
    /// Liquid Thought
    /// Created by:Rihan
    /// 
    /// Creates a combined datatable
    ///     Fetch records from CRM and put them in a table
    ///     Fetch records from KMS and put them in a table
    ///  
    ///     Combine the table
    /// 
    ///     
    /// </summary>
    [WebService(Namespace = "http://localhost/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    public class CombinedSearch : System.Web.Services.WebService
    {
        protected override void Dispose(bool disposing)
        {
            localService.Dispose();
            base.Dispose(disposing);
        }
        private CrmService localService;
        private Contact ShopperToSearchFor;
        /// <summary>
        /// Search method to use
        /// </summary>
        private searchType SearchType;

        public CombinedSearch() { localService = Common.CrmAutorize(); }
        /// <summary>
        /// Sets the search type from search parameters.
        /// </summary>
        /// <param name="searchParameter">The search parameter.</param>
        private void SetSearchTypeFromSearchParameters(string searchParameter)
        {
            SearchType = searchType.FullName;
            if (searchParameter.Contains("@"))
            {
                SearchType = searchType.EmailAddress;
            }
            Int32 idNumber;
            if (searchParameter.Length == 13 || Int32.TryParse(searchParameter, out idNumber))
            {
                if (Int32.TryParse(searchParameter, out idNumber))
                {
                    SearchType = searchType.IdNumber;
                }
            }
            Int32 phoneNumber;
            if (Int32.TryParse(searchParameter, out phoneNumber))
            {
                SearchType = searchType.PhoneNumber;

            }
        }
        #region WebMethodDescription
        /// <summary>
        /// Search can contain 3 types of parameters,
        /// a persons name or
        /// MobilePhoneNumber or
        /// _email address
        /// If the string contains a space, we assume that it is a persons name
        /// if the string contains a @ sign,we assume  that it is a _email address
        /// for the rest we try and locate a phone number / cell phone number
        /// </summary>
        /// <param name="searchParameter"><list type="bullet">
        /// 		<item>Contact LastName</item>
        /// 		<item>MobilePhoneNumber</item>
        /// 		<item>EmailAddress</item>
        /// 	</list></param>
        /// <returns></returns>
        DataTable searchResultsToReturn;
        [WebMethod(Description = "<summary> Search can contain 3 types of parameters," +
        "a persons name or " +
        "MobilePhoneNumber or " +
        "_email address " +
        "If the string contains a space, we assume that it is a persons name " +
        "if the string contains a @ sign,we assume  that it is a _email address" +
        "for the rest we try and locate a phone number / cell phone number" +
        "</summary>" +
        "<param name=searchParameter><list type=bullet>" +
        "		<item>Contact LastName</item>" +
        "		<item>MobilePhoneNumber</item>" +
        "		<item>EmailAddress</item>" +
        "	</list></param>" +
        "<returns></returns>")]
        #endregion WebMethodDescription

        public DataTable Search(string searchParameter)
        {
            if (!searchParameter.Contains("xxxxxxxxxxxxxx xxxxxxxxxx"))
            {
                SetSearchTypeFromSearchParameters(searchParameter);

                convertSearchStringToFields(searchParameter);

                DataTable crmSearchResults = SearchCrm(ShopperToSearchFor);
                SearchResult KmsShoppers = SearchKms(ShopperToSearchFor);

                searchResultsToReturn = SearchResults();
                if (crmSearchResults.Rows.Count > 0 &&
                        KmsShoppers.Shoppers != null
                    )
                {
                    foreach (Shopper shopper in KmsShoppers.Shoppers)
                    {
                        bool ShopperExistInCrm = false;
                        foreach (DataRow row in crmSearchResults.Rows)
                        {
                            if (
                                shopper.Email.Contains(row[Resource.CrmContactEmailAddressFieldName].ToString())
                                )
                            {
                                ShopperExistInCrm = true;
                            }
                        }
                        //Adding a single row, if the data exisist in both systems
                        if (ShopperExistInCrm == false)
                        {
                            DataRow kmsShopperRow = searchResultsToReturn.NewRow();
                            kmsShopperRow["FirstName"] = shopper.FirstName;
                            kmsShopperRow["LastName"] = shopper.LastName;
                            kmsShopperRow["Email"] = shopper.Email;
                            kmsShopperRow["IdNumber"] = shopper.IdNumber;
                            kmsShopperRow["SystemIdentifier"] = shopper.ShopperId;

                            searchResultsToReturn.Rows.Add(kmsShopperRow);
                        }
                    }
                    //Adding the CRM Results
                    foreach (DataRow crmResultRow in crmSearchResults.Rows)
                    {
                        searchResultsToReturn.Rows.Add(CreateSearchResultsRow(crmResultRow));
                    }

                }
                else
                {
                    //Adding KMS Shoppers
                    if (KmsShoppers.Shoppers != null)
                    {
                        foreach (Shopper shopper in KmsShoppers.Shoppers)
                        {
                            DataRow kmsShopperRow = searchResultsToReturn.NewRow();
                            kmsShopperRow["FirstName"] = shopper.FirstName;
                            kmsShopperRow["LastName"] = shopper.LastName;
                            kmsShopperRow["Email"] = shopper.Email;
                            kmsShopperRow["IdNumber"] = shopper.IdNumber;
                            kmsShopperRow["SystemIdentifier"] = shopper.ShopperId;

                            searchResultsToReturn.Rows.Add(kmsShopperRow);
                        }
                    }
                    //Adding CrmContacts
                    if (crmSearchResults.Rows.Count > 0)
                    {
                        foreach (DataRow row in crmSearchResults.Rows)
                        {
                            searchResultsToReturn.Rows.Add(CreateSearchResultsRow(row));
                        }
                    }

                }
            }
            return searchResultsToReturn;
            Dispose(true);
        }

        /// <summary>
        /// Creates the search results row.
        /// Handles that some columsn may not have been return by CRM, and therefor null
        /// </summary>
        /// <param name="sourceSystemDataRow">The source system data row.</param>
        /// <returns></returns>
        private DataRow CreateSearchResultsRow(DataRow sourceSystemDataRow)
        {
            DataRow localRow = searchResultsToReturn.NewRow();

            try { localRow["FirstName"] = sourceSystemDataRow["firstname"]; }
            catch { localRow["FirstName"] = ""; };
            try { localRow["LastName"] = sourceSystemDataRow["lastname"]; }
            catch { localRow["LastName"] = ""; }
            try { localRow["Email"] = sourceSystemDataRow["emailaddress1"]; }
            catch { localRow["Email"] = ""; }
            try { localRow["IdNumber"] = sourceSystemDataRow["new_idnumber"]; }
            catch { localRow["IdNumber"] = ""; }
            localRow["SystemIdentifier"] = sourceSystemDataRow["contactid"];

            return localRow;
        }
        /// <summary>
        /// Searches the results.
        /// </summary>
        /// <returns></returns>
        private DataTable SearchResults()
        {
            DataTable localTable = new DataTable();
            localTable.TableName = "searchResultsToReturn";
            localTable.Columns.Add("FirstName");
            localTable.Columns.Add("LastName");
            localTable.Columns.Add("Email");
            localTable.Columns.Add("IdNumber");
            localTable.Columns.Add("SystemIdentifier");
            return localTable;
        }


        /// <summary>
        /// Converts the search string to fields.
        /// This needs to be called before any of the search method's are executed, so that the local fields
        /// can be populated
        /// using the <typeparamref name="searchType"/> TypeOfSearchToPeform type
        /// <list type="bullet">
        /// <item>If it is a _email address, assign's the searchParameterToConvert to EmailAddress</item>
        /// <item>If it contains a space, splits the string using char.Parse(" ") and assign's the first value to first name, and
        /// second value to <paramref name="LastName"/>LastName</item>
        /// <item>If it is none of the above, assign's it to phone number</item>
        /// </list>
        /// When it is a full name search, it takes the string and tries to split it on space's
        /// if there is more than one spaces, the first "Word" will go to first name and all the subsequent words will go to last name.
        /// </summary>
        /// <param name="searchParameterToConvert">The search parameter to convert.</param>
        private void convertSearchStringToFields(string searchParameterToConvert)
        {
            ShopperToSearchFor = new Contact();

            switch (SearchType)
            {
                case searchType.EmailAddress:
                    ShopperToSearchFor.EmailAddress = searchParameterToConvert;
                    break;

                case searchType.FullName:
                    string[] NamedSearchParameters = searchParameterToConvert.Split(char.Parse(" "));

                    if (NamedSearchParameters.Length > 2)
                    {
                        ShopperToSearchFor.Firstname = NamedSearchParameters.GetValue(0).ToString();

                        for (int i = 1; NamedSearchParameters.Length > i; ++i)
                        {
                            ShopperToSearchFor.LastName = ShopperToSearchFor.LastName + " " + NamedSearchParameters.GetValue(i).ToString();
                        }
                    }
                    else
                    {
                        ShopperToSearchFor.FirstName = NamedSearchParameters.GetValue(0).ToString();
                        if (NamedSearchParameters.Length > 1)
                        { ShopperToSearchFor.LastName = NamedSearchParameters.GetValue(1).ToString(); }

                    }
                    break;

                case searchType.PhoneNumber:
                    ShopperToSearchFor.MobileNumber = searchParameterToConvert;
                    ShopperToSearchFor.PhoneNumber = searchParameterToConvert;
                    break;

                case searchType.ShopperId:
                    ShopperToSearchFor.ShopperId = searchParameterToConvert;
                    break;
            }
        }
        /// <summary>
        /// Fetches the parameters.
        /// </summary>
        /// <param name="ContactToCreateFetchParametersFrom">The contact to create fetch parameters from.</param>
        /// <returns></returns>
        private string FetchParameters(Contact ContactToCreateFetchParametersFrom)
        {
            System.Text.StringBuilder fetchParameters = new System.Text.StringBuilder();

            switch (SearchType)
            {
                case searchType.FullName:
                    fetchParameters.AppendFormat(Resources.Resource.FullNameSearchParameter, ContactToCreateFetchParametersFrom.Firstname, ContactToCreateFetchParametersFrom.LastName);
                    break;
                case searchType.EmailAddress:
                    fetchParameters.AppendFormat(Resources.Resource.EmailSearchParameter, ContactToCreateFetchParametersFrom.EmailAddress);
                    break;
                case searchType.IdNumber:
                    fetchParameters.AppendFormat(Resources.Resource.IdNumberSearchParameter, ContactToCreateFetchParametersFrom.PersonIdNumber);
                    break;
                case searchType.PhoneNumber:
                    fetchParameters.AppendFormat(Resources.Resource.TelephoneNumberSearchParameter, ContactToCreateFetchParametersFrom.PhoneNumber);
                    break;
            }

            return fetchParameters.ToString();
        }
        /// <summary>
        /// Searches crm,using fetch statements that is included in the resources file
        /// </summary>
        /// <param name="ContactToSearchFor">The contact to search for</param>
        /// <returns>Returns null, if no records are found</returns>
        private DataTable SearchCrm(Contact ContactToSearchFor)
        {
            System.Text.StringBuilder xmlFetch = new System.Text.StringBuilder();
            xmlFetch.AppendFormat(Resource.XmlFetchSearchContacts, FetchParameters(ContactToSearchFor));

            // Fetch the results.
            String results;
            try
            {
                results = localService.Fetch(xmlFetch.ToString());
            }
            catch (SoapException soapException)
            {
                results = soapException.Detail.InnerXml;
            }

            if (results != Resource.NoResults)
            {
                return ConvertIntoDataTable(results);
            }
            else
            {
                DataTable emptyTable = new DataTable();
                return emptyTable;
            }

        }

        /// <summary>
        /// Converts the crm results tring into tabledata .
        /// </summary>
        /// <param name="CrmFetchResultsString">The CRM fetch results string.</param>
        /// <returns>the result table</returns>
        private DataTable ConvertIntoDataTable(string CrmFetchResultsString)
        {
            DataSet ds = new DataSet();
            System.Data.DataTable dataTable = new DataTable();
            System.IO.StringReader reader = new System.IO.StringReader(CrmFetchResultsString);
            ds.ReadXml(reader);
            return ds.Tables["result"];
        }

        /// <summary>
        /// Searches the KMS.
        /// by calling the SearchShoppers web services
        /// then creating the authorization header, using username and password that is
        /// specified in the resources file
        /// </summary>
        /// <returns>No restrictions on the amount of shoppers that it searches on</returns>
        private SearchResult SearchKms(Contact shopperToSearchFor)
        {
            CRMService kmsSearchService = Common.KmsAuthorize();

            SearchResult result = kmsSearchService.SearchShoppers
                    (shopperToSearchFor.FirstName
                    , shopperToSearchFor.LastName
                    , shopperToSearchFor.PhoneNumber
                    , shopperToSearchFor.MobileNumber
                    , shopperToSearchFor.EmailAddress
                    , shopperToSearchFor.ShopperId
                    , shopperToSearchFor.OrderNumber
                    );
            return result;
        }
      
   
     


    }


}